#!/usr/bin/perl

#===============================================================================
#     REVISION:  $Id$
#  DESCRIPTION:  Test for Meter::Users
#===============================================================================

use strict;
use warnings;

use Readonly;
Readonly our $VERSION => qw($Revision$) [1];

use English qw( -no_match_vars );

#use Smart::Comments;
#$ENV{'DONT_CLEANUP'} = 1;

use Meter::Test qw(
    init_tmp_db
);

use Meter::Users;
use Meter::Utils qw(
    dump_compact
);

use Test::More tests => 7 + 2 + 2;
use Test::Exception;
use Test::DatabaseRow;

Readonly my $USERNAME => 'user1';
Readonly my $EMAIL    => 'email1@example.com';
Readonly my $PASSWORD => '123456';

Readonly my $INVALID_USERNAME => 'invalid user name!!!';
Readonly my $INVALID_EMAIL    => 'invalid@email@address@!!!';
Readonly my $INVALID_PASSWORD => 'x';

## no critic (ProhibitCommaSeparatedStatements)

sub test_common_case {
    my $user_fields = {
        username => $USERNAME,
        password => $PASSWORD,
        email    => $EMAIL,
    };

    # create user
    lives_ok {
        Meter::Users->insert($user_fields);
    }
    'Create user ' . dump_compact( $user_fields, 'USER' );

    row_ok(
        table => 'users',
        where => [ %{$user_fields} ],
        label => 'Check database row for '
            . dump_compact( $user_fields, 'USER' ),
    );

    # retrieve user by username and password
    my $user = Meter::Users->retrieve(
        username => $USERNAME,
        password => $PASSWORD,
    );

    ok( $user, "Retrieve user '$USERNAME'" );

    my $new_email = 'email1@example2.com';

    # update user
    lives_ok {
        $user->email($new_email);
        $user->update();
    }
    q{Update user's email }
        . dump_compact( { %{$user_fields}, email => $new_email },
        'UPDATED_USER' );

    row_ok(
        table => 'users',
        where => [ %{$user_fields}, email => $new_email ],
        label => 'Check database row for updated user '
            . dump_compact(
            { %{$user_fields}, email => $new_email },
            'UPDATED_USER'
            ),
    );

    # delete user
    lives_ok { $user->delete() } "Delete user '$USERNAME'";

    not_row_ok(
        table => 'users',
        where => [ username => $USERNAME ],
        label => "Check NO database row for deleted user '$USERNAME'",
    );

    return;
}

sub test_duplicated_entries {
    my $user_fields = {
        username => $USERNAME,
        password => $PASSWORD,
        email    => $EMAIL,
    };

    my $user = Meter::Users->insert($user_fields);

    throws_ok {
        Meter::Users->insert(
            { %{$user_fields}, email => 'new_email@example.com' } );
    }
    qr/\Qcolumn username is not unique\E/xms,
        "Try to create user with duplicated username '$USERNAME'";

    $user->delete();

    return;
}

sub test_invalid_field_contents {
    throws_ok {
        Meter::Users->insert(
            {   username => $INVALID_USERNAME,
                password => $PASSWORD,
                email    => $EMAIL,
            }
        );
    }
    qr/\Qusername fails 'regexp' constraint\E/xms,
        "Try to create user with invalid username '$INVALID_USERNAME'";

    throws_ok {
        Meter::Users->insert(
            {   username => $USERNAME,
                password => $INVALID_PASSWORD,
                email    => $EMAIL,
            }
        );
    }
    qr/\Qpassword fails 'regexp' constraint\E/xms,
        "Try to create user with invalid password '$INVALID_PASSWORD'";

    throws_ok {
        Meter::Users->insert(
            {   username => $USERNAME,
                password => $PASSWORD,
                email    => $INVALID_EMAIL,
            }
        );
    }
    qr/\Qemail fails 'regexp' constraint\E/xms,
        "Try to create user with invalid email '$INVALID_EMAIL'";

    return;
}

sub run_tests {
    init_tmp_db();

    test_common_case();
    test_duplicated_entries();
    test_invalid_field_contents();

    return;
}

run_tests();
